package org.jjj.car.service.impl;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.jjj.basic.config.MyResultMapper;
import org.jjj.basic.utils.PageList;
import org.jjj.car.es.doc.CarDoc;
import org.jjj.car.es.repository.CarDocRepository;
import org.jjj.car.query.CarSearchQuery;
import org.jjj.car.service.ICarSearchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

@Service
public class CarSearchServiceImpl implements ICarSearchService {
    //注入CarDocRepository用这个对象来操作es
    @Autowired
    private CarDocRepository carDocRepository;
    //做高亮查询
    @Autowired
    private MyResultMapper myResultMapper;
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;
    /**
     * 去es中查询数据
     * @param query
     * @return
     */
    @Override
    public PageList<CarDoc> list(CarSearchQuery query) {
        //1.创建QueryBuilder对象
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        //2.高级查询
        //进入到bool那一层
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //2.1关键字查询：相当于like
        if (StringUtils.isNotBlank(query.getKeyword())){
            boolQuery.must(QueryBuilders.multiMatchQuery(query.getKeyword(),"title","shopName","typeName","carInfo","shopAddress"));
        }
        //2.2过滤查询:filter
        Long typeId = query.getTypeId();//类型
        Integer costeffective = query.getCosteffective();//是否超值
        Integer quasinewcar = query.getQuasinewcar();//是否准新车
        Integer transitivecountry = query.getTransitivecountry();//可迁全国
        Integer rushsale = query.getRushsale();//是否急售
        if (typeId != null){
            //QueryBuilders.termQuery("typeId",typeId)相当于sql中的typeId=#{typeId}
            boolQuery.filter(QueryBuilders.termQuery("typeId",typeId));
        }
        if (costeffective != null){
            //QueryBuilders.termQuery("typeId",typeId)相当于sql中的typeId=#{typeId}
            boolQuery.filter(QueryBuilders.termQuery("costeffective",costeffective));
        }
        if (quasinewcar != null){
            //QueryBuilders.termQuery("typeId",typeId)相当于sql中的typeId=#{typeId}
            boolQuery.filter(QueryBuilders.termQuery("quasinewcar",quasinewcar));
        }
        if (transitivecountry != null){
            //QueryBuilders.termQuery("typeId",typeId)相当于sql中的typeId=#{typeId}
            boolQuery.filter(QueryBuilders.termQuery("transitivecountry",transitivecountry));
        }
        if (rushsale != null){
            //QueryBuilders.termQuery("typeId",typeId)相当于sql中的typeId=#{typeId}
            boolQuery.filter(QueryBuilders.termQuery("rushsale",rushsale));
        }
        //价格区间去查询
        BigDecimal minPrice = query.getMinPrice();
        BigDecimal maxPrice = query.getMaxPrice();
        if (minPrice != null){
            boolQuery.filter(QueryBuilders.rangeQuery("costprice").gte(minPrice));
        }
        if (maxPrice != null){
            boolQuery.filter(QueryBuilders.rangeQuery("costprice").lt(maxPrice));
        }
        //按照车龄查询
        Integer carAge = query.getCarAge();
        //0:以下；1以上
        Integer carAgeType = query.getCarAgeType();
        if (carAge!=null && carAgeType!=null){
            //取车龄的负数
            carAge=0-carAge;
            //取当前时间减去车龄就得到了参照时间，大于它就是以下，小于它就是以上
            Date date = DateUtils.addYears(new Date(), carAge);
            if (carAgeType ==0){
                boolQuery.filter(QueryBuilders.rangeQuery("reigstertime").gte(date));
            }else if (carAgeType ==1){
                boolQuery.filter(QueryBuilders.rangeQuery("reigstertime").lte(date));
            }
        }
        //将准备好的boolQuery对象交给builder
        builder.withQuery(boolQuery);
        //3.排序查询
        //拿到前端传来的排序字段jg,cl,lc,zxfb
        String sortField = query.getSortField();
        //desc:倒序，asc正序
        String sortType = query.getSortType();
        //默认是倒序
        SortOrder sortOrder = SortOrder.DESC;
        if ("asc".equals(sortType)){
            //如果前端传来的是正序那就取正序查
            sortOrder = SortOrder.ASC;
        }
        if ("jg".equals(sortField)){
            //SortBuilders.fieldSort("costprice").order(sortOrder)表示价格排序
            builder.withSort(SortBuilders.fieldSort("costprice").order(sortOrder));
        }else if("cl".equals(sortField)) {
            //表示车龄排序
            builder.withSort(SortBuilders.fieldSort("reigstertime").order(sortOrder));
        }else if("lc".equals(sortField)) {
            //表示里程排序
            builder.withSort(SortBuilders.fieldSort("mileage").order(sortOrder));
        }else if("zxfb".equals(sortField)) {
            //表示最新里程排序
            builder.withSort(SortBuilders.fieldSort("onsaletime").order(sortOrder));
        }
        //4.分页查询
        builder.withPageable(PageRequest.of((query.getCurrentPage()-1),query.getPageSize()));
        //5.高亮查询对象
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        //5.1设置要高亮展示的字段
        highlightBuilder.field("title");
        //5.2配置关键字前后的标签：怎样的样式来展示
        highlightBuilder.preTags("<span style=\"color: blue\">");
        highlightBuilder.postTags("</span>");
        //5.3交给QueryBuilder对象
        builder.withHighlightBuilder(highlightBuilder);
        //6.调search方法到es中查询
        //方式一：下面这种不支持高亮处理
//        Page<CarDoc> carDocs = carDocRepository.search(builder.build());
        //方式二：
        AggregatedPage<CarDoc> carDocs = elasticsearchTemplate.queryForPage(builder.build(), CarDoc.class, myResultMapper);
        //获取当前页数据
        List<CarDoc> rows = carDocs.getContent();
        for (CarDoc row : rows) {
            String shopAddress = row.getShopAddress();
            if (StringUtils.isNotBlank(shopAddress)){
                row.setShopAddress(shopAddress.split("区")[0]);
            }
        }
        //获取总条数
        long total = carDocs.getTotalElements();
        //7.封装返回给前端页面
        return new PageList<>(total,rows);
    }
}
